/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package SessionBeans.Sharing;

import SessionBeans.entites.FileService;
import SessionBeans.logs.FileChangeLogService;
import SessionBeans.logs.FolderChangeLogService;
import SessionBeans.web.beans.FileInfo;
import SessionBeans.web.beans.FolderInfo;
import SessionBeans.web.beans.FolderTypeEnum;
import SessionBeans.web.beans.OwnerUser;
import api.Rights.RightsEnum;
import entities.*;
import entities.Rights;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.security.PermitAll;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

/**
 *
 * @author Tomas
 */
@PermitAll
@Stateless
@LocalBean
public class SharingService {
    @EJB
    private RightsService rightsService;

    @EJB
    private FolderChangeLogService folderChangeLogService;
    @EJB
    private FileChangeLogService fileChangeLogService;
    @EJB
    private FileService fileService;
    @PersistenceContext(unitName = "tCloudEE-ejbPU")
    private EntityManager em;

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    public SharedFile saveSharedFile(Long ownerUserId, Long sharedUserId, Long fileId, Long rightsId) {
        User ownerUser = em.find(User.class, ownerUserId);
        User sharedUser = em.find(User.class, sharedUserId);
        File file = em.find(File.class, fileId);
        Rights rights = em.find(Rights.class, rightsId);

        return saveSharedFile(ownerUser, sharedUser, file, rights);
    }

    public SharedFile saveSharedFile(User ownerUser, User sharedUser, File file, Rights rights) {
        SharedFile sharedFile = new SharedFile();
        sharedFile.setFile(file);
        sharedFile.setOwnerUser(ownerUser);
        sharedFile.setSharedUser(sharedUser);
        sharedFile.setRights(rights);
        sharedFile.setSharedDate(new Date());

        sharedFile = em.merge(sharedFile);

        return sharedFile;
    }

    public SharedFolder saveSharedFolder(Long ownerUserId, Long sharedUserId, Long folderId, Long rightsId) {
        User ownerUser = em.find(User.class, ownerUserId);
        User sharedUser = em.find(User.class, sharedUserId);
        Folder folder = em.find(Folder.class, folderId);
        Rights rights = em.find(Rights.class, rightsId);

        return saveSharedFolder(ownerUser, sharedUser, folder, rights);
    }

    public SharedFolder saveSharedFolder(User ownerUser, User sharedUser, Folder folder, Rights rights) {
        SharedFolder sharedFolder = new SharedFolder();
        sharedFolder.setFolder(folder);
        sharedFolder.setOwnerUser(ownerUser);
        sharedFolder.setSharedUser(sharedUser);
        sharedFolder.setRights(rights);
        sharedFolder.setSharedDate(new Date());

        sharedFolder = em.merge(sharedFolder);

        return sharedFolder;
    }

    public List<SharedFile> loadSharedFile(Long fileId) {
        TypedQuery<SharedFile> createQuery = em.createQuery("Select OBJECT(u) from SharedFile u where u.file.id = " + fileId + "", SharedFile.class);
        return createQuery.getResultList();
    }

    public List<SharedFolder> loadSharedFolder(Long folderId) {
        TypedQuery<SharedFolder> createQuery = em.createQuery("Select OBJECT(u) from SharedFolder u where u.folder.id = " + folderId + "", SharedFolder.class);
        return createQuery.getResultList();
    }

    public void removeSharedFile(Long sharedFileId) {
        SharedFile find = em.find(SharedFile.class, sharedFileId);

        em.remove(find);
    }

    public void removeSharedFolder(Long sharedFolderId) {
        SharedFolder find = em.find(SharedFolder.class, sharedFolderId);

        em.remove(find);
    }

    public FolderInfo loadSharedAllData(Long userId) {
        List<FolderInfo> folders = loadSharedFoldersRec(userId, true);
        List<FileInfo> files = loadSharedAllFiles(userId);
        User find = em.find(User.class, userId);

        FolderChangeLog log = new FolderChangeLog(find.getCreated(), "Shared", -1l, new OperationType(1l, "NEW"), userId);
        Folder folder = new Folder(-1l, "Shared", 0l);
        OwnerUser owner = new OwnerUser(userId, find.getName());

        return new FolderInfo(folder, folders, files, log, rightsService.loadRights(RightsEnum.DELETE), owner, FolderTypeEnum.SHARED);
    }

    public FolderInfo loadShareData(Long userId) {
        List<FolderInfo> folders = loadSharedFoldersRec(userId, false);
        List<FileInfo> files = loadSharedAllFiles(userId);

        User find = em.find(User.class, userId);

        FolderChangeLog log = new FolderChangeLog(find.getCreated(), "Shared", -1l, new OperationType(1l, "NEW"), userId);
        Folder folder = new Folder(-1l, "Shared", 0l);
        folder.setParentFolder(find.getAccountHeaderList().get(0).getRootFolder());
        OwnerUser owner = new OwnerUser(userId, find.getName());

        return new FolderInfo(folder, folders, files, log, rightsService.loadRights(RightsEnum.DELETE), owner, FolderTypeEnum.SHARED);
    }

    public List<FileInfo> loadSharedAllFiles(Long userId) {
        TypedQuery<SharedFile> createQuery = em.createQuery("Select OBJECT(u) from SharedFile u where u.sharedUser.id = " + userId + "", SharedFile.class);
        List<SharedFile> resultList = createQuery.getResultList();

        List<FileInfo> fileInfos = new ArrayList<>();

        for (SharedFile sharedFile : resultList) {
            OwnerUser owner = new OwnerUser(sharedFile.getOwnerUser().getId(), sharedFile.getOwnerUser().getName());

            fileInfos.add(new FileInfo(sharedFile.getFile(), sharedFile.getRights(), owner,
                    fileService.loadFileSize(sharedFile.getFile()), fileChangeLogService.loadLastChange(sharedFile.getFile())));
        }

        return fileInfos;
    }

    public List<FolderInfo> loadSharedFoldersRec(Long userId, boolean recursive) {
        TypedQuery<SharedFolder> createQuery = em.createQuery("Select OBJECT(u) from SharedFolder u where u.sharedUser.id = " + userId + "", SharedFolder.class);
        List<SharedFolder> resultList = createQuery.getResultList();

        List<FolderInfo> folderInfos = new ArrayList<>();


        for (SharedFolder sharedFolder : resultList) {
            OwnerUser owner = new OwnerUser(sharedFolder.getOwnerUser().getId(), sharedFolder.getOwnerUser().getName());
            FolderInfo next;
            if (recursive) {
                next = loadSharedFolderRec(sharedFolder.getFolder(), sharedFolder.getRights(), owner);
            } else {
                next = new FolderInfo(sharedFolder.getFolder(), folderChangeLogService.loadLastChange(sharedFolder.getFolder()), FolderTypeEnum.SHARED, owner, sharedFolder.getRights());
            }
            folderInfos.add(next);
        }

        return folderInfos;
    }

    private FolderInfo loadSharedFolderRec(Folder folder, Rights rights, OwnerUser owner) {
        FolderInfo result = new FolderInfo(folder, folderChangeLogService.loadLastChange(folder), FolderTypeEnum.SHARED, owner, rights);
        List<FileInfo> files = new ArrayList<>();
        List<FolderInfo> folders = new ArrayList<>();

        for (File file : folder.getFilesList()) {
            files.add(new FileInfo(file, rights, owner, fileService.loadFileSize(file), fileChangeLogService.loadLastChange(file)));
        }

        result.setFiles(files);

        for (Folder folderChild : folder.getFolderList()) {
            folders.add(loadSharedFolderRec(folderChild, rights, owner));
        }

        return result;
    }
}
